#include <hd_led.h>
#include <hd_oled.h>
#include <hd_oled_protocol_i2c.h>
#include <pd_i2c_sim.h>
#include <hd_mpu6050.h>
#include <pd_i2c_hd.h>
#include <hd_ina226.h>
#include <delay.h>
#include <pd_spi_io.h>
#include <stddef.h>
#include <pd_spi_hd.h>
#include <hd_oled_protocol_spi.h>
#include "main.h"


#define ARRAY_SIZE(x)       sizeof(x) / sizeof(x[0])
#define USE_HARDWARE_SPI    1
#define USE_HARDWARE_I2C    1
OLED oled;

extern void SystemClock_Config(void);

void oled_instance(OLED *oled);

int main(void) {
    SystemClock_Config();

    NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2);

    oled_instance(&oled);

    GPIO i2cSCK, i2cSDA;
    GPIO_constructor(&i2cSCK, GPIOA, LL_GPIO_PIN_8);
    GPIO_constructor(&i2cSDA, GPIOC, LL_GPIO_PIN_9);

    I2CHardware i2cHard;
    I2CHardware_constructor(&i2cHard, I2C3, &i2cSCK, &i2cSDA);
    I2C *i2c4INA226 = (I2C *)&i2cHard;
    I2C_init(i2c4INA226);

    INA226 ina226 ;
    INA226_constructor(&ina226, i2c4INA226);
    INA226_init(&ina226);


    uint16_t val;
    INA226_readManuId(&ina226, &val);
    OLED_printf(&oled, 0, 00, "%04d", val);

    val = 0;
    INA226_readDieId(&ina226, &val);
    OLED_printf(&oled, 64, 00, "%04d", val);

    OLED_refresh(&oled);
    delay_ms(3000);
    OLED_clear(&oled);

    OLED_printf(&oled, 112, 00, "mV");
    OLED_printf(&oled, 112, 16, "mV");
    OLED_printf(&oled, 112, 32, "mA");
    OLED_printf(&oled, 112, 48, "mW");
    OLED_refresh(&oled);

    while (1) {
        INA226_readShunt(&ina226, &val);
        OLED_printf(&oled, 0, 00, "%05d", val);
        OLED_showFloat(&oled, 64, 00, val * 2.5 * 0.001, 5);

        INA226_readBus(&ina226, &val);
        OLED_printf(&oled, 0, 16,"%05d", val);
        OLED_showFloat(&oled, 64, 16, val * 1.25, 5);

        INA226_readCurrent(&ina226, &val);
        OLED_printf(&oled, 0, 48, "%05d", val);
        OLED_showFloat(&oled, 64, 48, val * 0.02, 5);

        INA226_readPower(&ina226, &val);
        OLED_printf(&oled, 0, 32, "%05d", val);
        OLED_showFloat(&oled, 64, 32, val * 25 * 0.02, 5);

        OLED_refresh(&oled);
        delay_ms(200);
    }
}


void oled_instance(OLED *oled) {
    // I2C gpio init
    static GPIO oledSckGPIO, oledSdaGPIO;
    GPIO_constructor(&oledSckGPIO, GPIOB, LL_GPIO_PIN_10); // I2Cx_SCK
    GPIO_constructor(&oledSdaGPIO, GPIOB, LL_GPIO_PIN_11); // I2Cx_SDA

#ifdef USE_HARDWARE_I2C
    static I2CHardware i2c2;
    I2CHardware_constructor(&i2c2, I2C2, &oledSckGPIO, &oledSdaGPIO);
#elif USE_SIMULATE_I2C
    static I2CSimulate i2c2;
    I2CSimulate_constructor(&i2c2, &oledSckGPIO, &oledSdaGPIO);
#endif
    I2C_init((I2C *)&i2c2);

    // OLED protocol of I2C
    static OLEDProtocolI2C oledProtocolI2c;
    OLEDProtocolI2C_constructor(&oledProtocolI2c, (I2C *)&i2c2);

    // OLED font instance.
    static OLEDFont oledFont;
    OLEDFont_contructor(&oledFont, NULL);

    // OLED instance of 4-PIN(I2C)
    OLED_constructor(oled, (OLEDProtocol *)&oledProtocolI2c, &oledFont);

    OLED_init(oled);

    OLED_clear(oled);
    OLED_refresh(oled);
}
